/**
 * Project of Vehicle Routing Problem with Time Windows implements 
 * some of well-known algorithms for solving VRPTW and presents new 
 * one.
 *
 * @author Michal Drobny  
 */

package logic.route;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import logic.destination.Destination;
import logic.restriction.interfaces.HasDestinations;

/**
 * Represents the cycle in route. This object is usually served as a result of
 * algorithm for VRP. Contains destinations, whose must be ordered to cycle.
 * 
 * @author Michal Drobny
 * @date 18.10.2014
 */
public class Cycle implements HasDestinations {

	private LinkedList<Destination> destinations;

	/**
	 * Constructor.
	 */
	public Cycle() {
		super();
		destinations = new LinkedList<Destination>();
	}

	/**
	 * Constructor.
	 * 
	 * @param destinations
	 */
	public Cycle(List<Destination> destinations) {
		super();
		this.destinations = new LinkedList<Destination>(destinations);
	}

	/**
	 * Adds given destination to the end of cycle.
	 * 
	 * @param destination
	 *            The destination
	 */
	public void addToEnd(Destination destination) {

		if (destination == null)
			return;

		if (destinations.contains(destination))
			return;

		destinations.addLast(destination);
	}

	/**
	 * Adds the destination 'what' to the place after destination 'where' in the
	 * list of destinations.
	 * 
	 * @param what
	 *            The destination to add
	 * @param where
	 *            The destination which should be previous to added destination
	 *            after action
	 */
	public void addAfter(Destination what, Destination where) {

		if (what == null || where == null)
			return;

		if (destinations.contains(what))
			return;

		ListIterator<Destination> iterator = destinations.listIterator();
		while (iterator.hasNext()) {
			Destination currentDest = iterator.next();
			if (currentDest.equals(where)) {
				iterator.add(what);
				break;
			}
		}
	}

	/**
	 * Adds the destination 'what' to the place specified by the position.
	 * 
	 * @param position
	 *            The position
	 * @param what
	 *            The destination to add
	 */
	public void addToPosition(int position, Destination what) {

		if (what == null || position < 0)
			return;

		if (position > destinations.size() || destinations.contains(what))
			return;

		destinations.add(position, what);
	}

	@Override
	public List<Destination> getDestinations() {
		return destinations;
	}

	/**
	 * Removes the specified destination.
	 * 
	 * @param destination
	 *            The destination to remove from list of destinations
	 */
	public void remove(Destination destination) {
		if (destination == null)
			return;
		
		destinations.remove(destination);
	}

	/**
	 * Whether the destinations is empty.
	 * 
	 * @return whether the destinations is empty
	 */
	public boolean isEmpty() {
		return destinations.isEmpty();
	}

	/**
	 * Gets the count of destinations in cycle.
	 * 
	 * @return count of destinations
	 */
	public int size() {
		return destinations.size();
	}
}